package com.toro.client;

import com.toro.client.handler.HeartBeatClientHandler;
import com.toro.client.handler.MyChannelInboundHandlerAdapter;
import com.toro.client.handler.RpcResponseMessageHandler;
import com.toro.config.Config;
import com.toro.protocol.MessageCodecSharable;
import com.toro.protocol.ProcotolFrameDecoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @ClassName: ChatClient
 * @Description:
 * @Author: ToroLHZ
 * @Date: 2023/12/11 17:11
 */
@Slf4j
public class ChatClient {
    public static void main(String[] args) {
        NioEventLoopGroup group = new NioEventLoopGroup();
        LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
        RpcResponseMessageHandler RPC_HANDLER = new RpcResponseMessageHandler();
        //20秒没有写入数据就发送心跳数据
        IdleStateHandler STATE_HANDLER = new IdleStateHandler(0, Config.getHeartSend(), 0);
        HeartBeatClientHandler HEARTBEAT_HANDLER = new HeartBeatClientHandler();
        CountDownLatch WAIT_FORLOGIN = new CountDownLatch(1);
        AtomicBoolean LOGIN = new AtomicBoolean(false);
        MyChannelInboundHandlerAdapter INBOUND_HANDLER = new MyChannelInboundHandlerAdapter(LOGIN, WAIT_FORLOGIN);


        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.group(group);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    //粘包半包类优化
                    ch.pipeline().addLast(new ProcotolFrameDecoder());
                    //日志
                    ch.pipeline().addLast(LOGGING_HANDLER);
                    //编解码可sharable
                    ch.pipeline().addLast(MESSAGE_CODEC);
                    //RPC_HANDLER
//                    ch.pipeline().addLast(RPC_HANDLER);
                    //用来判断是不是读空闲时间过长或写空闲时间过长,规定时间写入心跳
                    ch.pipeline().addLast(STATE_HANDLER);
                    //全双工处理器出栈和入栈处理器(发送心跳)
                    ch.pipeline().addLast(HEARTBEAT_HANDLER);
                    //用户操作页面处理器
                    ch.pipeline().addLast("client handler", INBOUND_HANDLER);
                }
            });
            Channel channel = bootstrap.connect(Config.getClientIP(), Config.getClientPort()).sync().channel();
            log.info("客户端启动成功，连接ip:{},连接端口：{}", Config.getClientIP(), Config.getClientPort());
            channel.closeFuture().sync();
        } catch (Exception e) {
            log.error("客户端异常,原因：{}", e.getMessage());
        } finally {
            group.shutdownGracefully();
            log.info("客户端关闭");
        }
        log.info("客户端程序结束");
    }

}
